/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.java; import java.io.*; import java.beans.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import org.openide.*; import org.openide.cookies.OpenCookie; import org.openide.filesystems.*; import org.openide.nodes.*; import org.openide.loaders.DataNode; import org.openide.loaders.ExecSupport; import org.openide.loaders.CompilerSupport; import org.openide.loaders.MultiDataObject; import org.openide.src.*; import org.openide.src.nodes.SourceChildren; import org.openide.util.HelpCtx; import org.openide.util.RequestProcessor; import org.openide.util.Task; /** The node representation of <code>JavaDataObject</code> for Java sources. * * @author Petr Hamernik */ public class JavaNode extends DataNode { /** generated Serialized Version UID */ static final long serialVersionUID = -7396485743899766258L; private static final String EXECUTION_SET_NAME = "Execution"; // NOI18N private static final String PROP_SYNCHRONIZATION_MODE = "SynchMode"; // NOI18N private static final String ICON_BASE = "org/netbeans/modules/java/resources/"; // NOI18N private static final String[] ICONS = { "class", "classMain", "classError", "class", "classMain" // NOI18N }; private static final byte ICON_CLASS = 0; private static final byte ICON_CLASS_MAIN = 1; private static final byte ICON_CLASS_ERROR = 2; private static final byte ICON_BEAN = 3; private static final byte ICON_BEAN_MAIN = 4; private byte currentIcon; /** Create a node for the Java data object using the default children. * @param jdo the data object to represent */ public JavaNode (JavaDataObject jdo) { /* Changed for multiple factories * this(jdo, new SourceChildren(JavaElementNodeFactory.DEFAULT, jdo.getSource())); */ this(jdo, new SourceChildren(JavaDataObject.getExplorerFactory(), jdo.getSource())); } /** Create a node for the Java data object with configurable children. * Subclasses should use this constructor if they wish to provide special display for the child nodes. * Typically this would involve creating a subclass of {@link SourceChildren} based * on the {@link JavaDataObject#getSource provided source element}; the children list * may have extra nodes {@link Children#add(Node[]) added}, either at the {@link Children.Keys#setBefore beginning or end}. * @param jdo the data object to represent * @param children the children for this node */ public JavaNode (JavaDataObject jdo, Children children) { super (jdo, children); currentIcon = ICON_CLASS; initialize(); } private void initialize () { setIconBase(getIconBase() + getIcons()[currentIcon]); getJavaDataObject().getSource().addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { sourcePropertyChange(evt); } }); } void sourcePropertyChange(PropertyChangeEvent evt) { firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); if (ElementProperties.PROP_STATUS.equals(evt.getPropertyName())) requestResolveIcons(); } private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { is.defaultReadObject(); initialize(); } /** Create the property sheet. * Subclasses may want to override this and add additional properties. * @return the sheet */ protected Sheet createSheet () { Sheet sheet = super.createSheet(); Sheet.Set ps = sheet.get(Sheet.PROPERTIES); ps.put(new PropertySupport.ReadWrite ( PROP_SYNCHRONIZATION_MODE, Byte.class, Util.getString("PROP_synchMode"), Util.getString("HINT_synchMode") ) { public Object getValue() { return new Byte(getJavaDataObject().getSynchronizationType()); } public void setValue (Object val) throws InvocationTargetException { if (val instanceof Byte) { try { getJavaDataObject().setSynchronizationType(((Byte) val).byteValue()); return; } catch(IllegalArgumentException e) { } } throw new IllegalArgumentException(); } public PropertyEditor getPropertyEditor() { return new SyncModeEditor(); } }); ps = new Sheet.Set (); ps.setName(EXECUTION_SET_NAME); ps.setDisplayName(Util.getString("PROP_executionSetName")); ps.setShortDescription(Util.getString("HINT_executionSetName")); ExecSupport es = (ExecSupport) getCookie (ExecSupport.class); if (es != null) es.addProperties (ps); CompilerSupport cs = (CompilerSupport) getCookie (CompilerSupport.class); if (cs != null) cs.addProperties (ps); sheet.put(ps); return sheet; } /** Get the associated Java data object. * ({@link #getDataObject} is protected; this provides access to it.) * @return the data object */ protected JavaDataObject getJavaDataObject() { return (JavaDataObject) getDataObject(); } void requestResolveIcons() { SourceElementImpl.PARSING_RP.postRequest( new Runnable () { public void run () { resolveIcons (); } } ); } /** Get the icon base. * This should be a resource path, e.g. <code>/some/path/</code>, * where icons are held. Subclasses may override this. * @return the icon base * @see #getIcons */ protected String getIconBase() { return ICON_BASE; } /** Get the icons. * This should be a list of bare icon names (i.e. no extension or path) in the icon base. * It should contain five icons in order for: * <ul> * <li>a regular class * <li>a class with a main method * <li>a class with a parse error * <li>a JavaBean class * <li>a JavaBean class with a main method * </ul> * Subclasses may override this. * @return the icons * @see #getIconBase */ protected String[] getIcons() { return ICONS; } /** Update the icon for this node based on parse status. * Called automatically at the proper times. * @see #getIconBase * @see #getIcons */ protected void resolveIcons() { SourceElement source = getJavaDataObject().getSource(); byte newIcon = ICON_CLASS; String desc = null; switch (source.getStatus()) { case SourceElement.STATUS_NOT : newIcon = currentIcon; break; case SourceElement.STATUS_ERROR: case SourceElement.STATUS_PARTIAL: desc = Util.getString("HINT_ParsingErrors"); newIcon = ICON_CLASS_ERROR; break; case SourceElement.STATUS_OK: Task task = source.prepare(); FileObject fo = getJavaDataObject().getPrimaryEntry().getFile(); String name = fo.getName(); fo = fo.getParent(); String pack = (fo == null) ? "" : fo.getPackageName('.'); // NOI18N // check the package Identifier id = source.getPackage(); String pack2 = (id == null) ? "" : id.getFullName(); // NOI18N if (!pack.equals(pack2)) { desc = new MessageFormat(Util.getString("FMT_Bad_Package")).format(new Object[] { pack2 }); // newIcon = ICON_CLASS_ERROR; break; } // check the runnable and javabean ClassElement[] classes = source.getClasses(); boolean runnable = false; boolean javaBean = false; for (int i = 0; i < classes.length; i++) { if (classes[i].getName().getName().equals(name)) { runnable = classes[i].hasMainMethod(); javaBean = classes[i].isDeclaredAsJavaBean(); break; } } newIcon = (runnable) ? (javaBean ? ICON_BEAN_MAIN : ICON_CLASS_MAIN) : (javaBean ? ICON_BEAN : ICON_CLASS); break; } setShortDescription(desc); if (currentIcon != newIcon) { currentIcon = newIcon; setIconBase(getIconBase() + getIcons()[currentIcon]); } } /** Simple property editor for two-item pulldown. */ static class SyncModeEditor extends PropertyEditorSupport { private static final String[] tags; static { tags = new String[3]; tags[JavaDataObject.CONNECT_NOT] = Util.getString("CTL_CONNECT_NOT"); tags[JavaDataObject.CONNECT_CONFIRM] = Util.getString("CTL_CONNECT_CONFIRM"); tags[JavaDataObject.CONNECT_AUTO] = Util.getString("CTL_CONNECT_AUTO"); } public String[] getTags () { return tags; } public String getAsText () { return tags[((Byte) getValue ()).byteValue ()]; } public void setAsText (String text) throws IllegalArgumentException { for (byte i = 0; i < tags.length; i++) { if (tags[i].equals (text)) { setValue (new Byte(i)); return; } } throw new IllegalArgumentException (); } } /** Called when an object is to be copied to clipboard. * @return the transferable object dedicated to represent the * content of clipboard * @exception NodeAccessException is thrown when the * operation cannot be performed */ /* public TransferableOwner clipboardCopy () throws IOException { JavaDataObject obj = (JavaDataObject) getDataObject (); if (obj.decideJavaBeanFromClass ()) { Class c = obj.getClazz (); return new BeanTransferableOwner (super.clipboardCopy (), c.getName (), c); } else return super.clipboardCopy (); } */ /* static class BeanTransferableOwner extends TransferableOwner.Filter { String beanName; BeanTransferableOwner (TransferableOwner transferable, String beanName, Class beanClass) { super (transferable, new DataFlavor[] {new TransferFlavors.BeanFlavor (beanClass)}); this.beanName = beanName; } */ /** Creates transferable data for this flavor. */ /* public Object getTransferData (DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (isDataFlavorSupported(flavor)) { if (flavor instanceof TransferFlavors.BeanFlavor) return beanName; return super.getTransferData (flavor); } else { // not supported flavor throw new UnsupportedFlavorException (flavor); } } } */ } /* * Log * 49 Gandalf 1.48 1/12/00 Petr Hamernik i18n: perl script used ( * //NOI18N comments added ) * 48 Gandalf 1.47 1/3/00 Petr Jiricka Properties for execution * and compilation are added only when the corresponding cookies are found * (fixes NullPointerException when replacing ExecSupport and * CompilerSupport) * 47 Gandalf 1.46 10/29/99 Jesse Glick Using undeprecated * variant of *Support.addProperties. * 46 Gandalf 1.45 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems copyright in file comment * 45 Gandalf 1.44 10/7/99 Petr Hamernik Java module has its own * RequestProcessor for source parsing. * 44 Gandalf 1.43 9/10/99 Petr Hamernik some import removed * 43 Gandalf 1.42 9/10/99 Jaroslav Tulach Changes to services. * 42 Gandalf 1.41 8/6/99 Petr Hamernik Working with threads * improved * 41 Gandalf 1.40 8/2/99 Petr Hamernik hopefully deadlock * prevention * 40 Gandalf 1.39 7/28/99 Ian Formanek Bean icon removed (the * basic class icon is used for beans as well) * 39 Gandalf 1.38 7/15/99 Ian Formanek Fixed bug 1741 - * Canceling String Property Editor issues exception * 38 Gandalf 1.37 6/28/99 Petr Hrebejk Multiple node factories * added * 37 Gandalf 1.36 6/10/99 Petr Hamernik wrong package doesn't * affect the icon * 36 Gandalf 1.35 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 35 Gandalf 1.34 6/7/99 Petr Hamernik resolving icons * transferred to AWT-EventQueue * 34 Gandalf 1.33 6/5/99 Petr Hamernik temporary - resolving * icons disabled! * 33 Gandalf 1.32 6/2/99 Petr Hamernik connections of java * sources * 32 Gandalf 1.31 5/12/99 Petr Hamernik ide.src.Identifier * changed * 31 Gandalf 1.30 5/10/99 Jaroslav Tulach DataNode.canRename * 30 Gandalf 1.29 5/6/99 Jesse Glick [JavaDoc] * 29 Gandalf 1.28 5/6/99 Petr Hamernik constructor with * Children added * 28 Gandalf 1.27 5/6/99 Jesse Glick [JavaDoc] * 27 Gandalf 1.26 4/23/99 Petr Hamernik icons bugfix * 26 Gandalf 1.25 4/21/99 Petr Hamernik debugs removed * 25 Gandalf 1.24 4/21/99 Petr Hamernik Java module updated * 24 Gandalf 1.23 4/15/99 Martin Ryzl getters for icons and * icon base added * 23 Gandalf 1.22 4/7/99 Petr Hamernik package property changed * 22 Gandalf 1.21 4/6/99 Petr Hamernik bugfixes * 21 Gandalf 1.20 4/2/99 Petr Hamernik * 20 Gandalf 1.19 4/2/99 Petr Hamernik * 19 Gandalf 1.18 4/2/99 Petr Hamernik * 18 Gandalf 1.17 4/1/99 Petr Hamernik * 17 Gandalf 1.16 4/1/99 Petr Hamernik * 16 Gandalf 1.15 3/29/99 Petr Hamernik * 15 Gandalf 1.14 3/22/99 Ian Formanek Icons moved from * modules/resources to this package * 14 Gandalf 1.13 3/19/99 Ales Novak * 13 Gandalf 1.12 3/18/99 Petr Hamernik * 12 Gandalf 1.11 3/16/99 Petr Hamernik renaming static fields * 11 Gandalf 1.10 3/15/99 Petr Hamernik * 10 Gandalf 1.9 3/12/99 Petr Hamernik * 9 Gandalf 1.8 3/10/99 Petr Hamernik * 8 Gandalf 1.7 2/25/99 Petr Hamernik * 7 Gandalf 1.6 2/18/99 Petr Hamernik * 6 Gandalf 1.5 2/11/99 Petr Hamernik * 5 Gandalf 1.4 1/20/99 Petr Hamernik * 4 Gandalf 1.3 1/15/99 Petr Hamernik * 3 Gandalf 1.2 1/15/99 Petr Hamernik * 2 Gandalf 1.1 1/13/99 Petr Hamernik * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ * Beta Change History: * 0 Tuborg 0.14 --/--/98 Jan Formanek icons added * 0 Tuborg 0.15 --/--/98 Petr Hamernik new text editor, parsing added... * 0 Tuborg 0.16 --/--/98 Petr Hamernik Parsing... * 0 Tuborg 0.17 --/--/98 Jan Formanek removed isCompilationAllowed (the inherited impl already works) * 0 Tuborg 0.18 --/--/98 Petr Hamernik small change * 0 Tuborg 0.19 --/--/98 Jan Formanek static reference to parserManager moved to JavaLoader * 0 Tuborg 0.20 --/--/98 Petr Hamernik localization,... * 0 Tuborg 0.22 --/--/98 Jan Jancura moved to propertySet * 0 Tuborg 0.23 --/--/98 Jan Formanek changed parseChanged semantics - it does not create and * 0 Tuborg 0.23 --/--/98 Jan Formanek set the children if the node has not been initialized. * 0 Tuborg 0.23 --/--/98 Jan Formanek This allows the children to be created from the createInitNodes * 0 Tuborg 0.23 --/--/98 Jan Formanek method (so that the subclasses can do something in there) * 0 Tuborg 0.24 --/--/98 Jan Formanek createJavaItemNodes renamed to createSubNodes and made protected * 0 Tuborg 0.25 --/--/98 Petr Hamernik readobject * 0 Tuborg 0.26 --/--/98 Jan Formanek reflecting changes in cookies * 0 Tuborg 0.28 --/--/98 Jan Formanek templates */